package com.zhb.cloud.utils;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.util.Base64;
import java.util.Objects;
import java.util.Optional;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.jupiter.api.Test;

/**
 * @ClassName: AESEncryptUtil
 * @Description:AES加密工具类
 * @author: zhb1316783262@163.com
 * @date: 2019年4月18日下午5:55:11
 *
 */
public class AESEncryptUtil {
	/**
	 * 加密算法
	 */
	public static final String KEY_ALGORITHM = "AES";

	public enum AES_KEY_SIZE {
		/**
		 * 秘钥长度为128
		 */
		KEY_LENGTH_128(128),
		/**
		 * 密钥长度为192
		 */
		KEY_LENGTH_192(192),
		/**
		 * 秘钥长度为256
		 */
		KEY_LENGTH_256(256);

		AES_KEY_SIZE(final int size) {
			this.keyLength = size;
		}

		private final int keyLength;

		public int getKeyLength() {
			return this.keyLength;
		}
	}

	/**
	 * 加密算法，分组模式，填充模式
	 */
	public static final String CIPHER_ALGORITHM = "AES/ECB/PKCS7Padding";

	public static byte[] generKey() {
		return generKey(AES_KEY_SIZE.KEY_LENGTH_256);
	}

	public static byte[] generKey(final AES_KEY_SIZE keySize) {
		try {
			KeyGenerator kgen = KeyGenerator.getInstance(KEY_ALGORITHM);
			AES_KEY_SIZE aesKeySize = Optional.ofNullable(keySize).orElse(AES_KEY_SIZE.KEY_LENGTH_128);
			kgen.init(aesKeySize.getKeyLength());
			SecretKey secretKey = kgen.generateKey();
			return secretKey.getEncoded();
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException(e);
		}
	}

	public static String generKeyToBase64(final AES_KEY_SIZE keySize) {
		return Base64.getEncoder().encodeToString(generKey(keySize));
	}

	public static String generKeyToHex(final AES_KEY_SIZE keySize) {
		return HexUtil.bytesToHex(generKey(keySize));
	}

	public static String generKeyToBase64() {
		return Base64.getEncoder().encodeToString(generKey());
	}

	protected static Key toKey(final byte[] key) {
		return new SecretKeySpec(key, KEY_ALGORITHM);
	}

	protected static Key toKey(final String pwd) {
		byte[] key = Base64.getDecoder().decode(pwd);
		return toKey(key);
	}

	/**
	 * @param content 明文数据
	 * @param pwd     Base64编码的密钥
	 * @return 加密数据
	 */
	public static byte[] encrypt(final byte[] content, final String pwd) {
		return encryptService(content, pwd, Cipher.ENCRYPT_MODE);
	}

	/**
	 * @param content 明文数据
	 * @param pwd     Base64编码的密钥
	 * @return 加密数据
	 */
	public static String encrypt(final String content, final String pwd) {
		return Base64.getEncoder().encodeToString(encryptService(content.getBytes(), pwd, Cipher.ENCRYPT_MODE));
	}

	/**
	 * @param content 密文数据
	 * @param pwd     Base64编码的密钥
	 * @return 明文数据
	 */
	public static byte[] decrypt(final byte[] content, final String pwd) {
		return encryptService(content, pwd, Cipher.DECRYPT_MODE);
	}

	/**
	 * @param content 密文数据
	 * @param pwd     Base64编码的密钥
	 * @return 明文数据
	 */
	public static byte[] decrypt(final byte[] content, final byte[] pwd) {
		return encryptService(content, pwd, Cipher.DECRYPT_MODE);
	}

	public static byte[] decrypt(String base64Content, final String pwd) {
		return encryptService(Base64.getDecoder().decode(base64Content), pwd, Cipher.DECRYPT_MODE);
	}

	private static byte[] encryptService(final byte[] content, final byte[] pwd, int model) {
		Objects.requireNonNull(content, "明文数据不能为空");
		Objects.requireNonNull(pwd, "密钥信息不能为空");
		try {
			initBC();
			Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM, "BC");
			cipher.init(model, toKey(pwd));
			return cipher.doFinal(content);
		} catch (NoSuchAlgorithmException | NoSuchProviderException | NoSuchPaddingException | InvalidKeyException
				| IllegalBlockSizeException | BadPaddingException e) {
			throw new RuntimeException(e);
		}
	}

	private static byte[] encryptService(final byte[] content, final String pwd, int model) {
		Objects.requireNonNull(content, "明文数据不能为空");
		Objects.requireNonNull(pwd, "密钥信息不能为空");
		try {
			initBC();
			Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM, "BC");
			cipher.init(model, toKey(pwd));
			return cipher.doFinal(content);
		} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException
				| BadPaddingException | NoSuchProviderException e) {
			throw new RuntimeException(e);
		}
	}

	private static void initBC() {
		Security.addProvider(new BouncyCastleProvider());
	}

	@Test
	public void main() throws UnsupportedEncodingException {
		String key = generKeyToBase64(AES_KEY_SIZE.KEY_LENGTH_256);
		String key1 = generKeyToHex(AES_KEY_SIZE.KEY_LENGTH_256);
		System.out.println(key);
		System.out.println(key1);
		String des = "qmkqWLDNBMv4QHvupM0KTX3sIXps4AwCctzBTadSpdqxrM5sQfUdDxVcPfFbGcu1X/BEmEz5HoeO0JCDNgTklfE9ZNCmfDKQxc/3IUXCm2iNdeEPqGzX6TjZBxgy2nf48wgsCaw3S22lXWGSyt2mJj98XaYgLF3NBVvejxCMr9QNtCYyQ8veswO1w7TjQsXcLuZ5iUZaRtBpk+NwGf8xMcevi4+gVIP43aWnRDCaR2kkXavvgTJOYqwv9ZQsG83ksUcWS3spSW1/BXcs7FjWDJFAyFDXAXlPMZo2UA7/zh9JsYF0FLY8ydEl22JtNZMw4pldB5tPv3xlPZo0PGhJqx1ktHTuF0hHhBYCjT/X3hxwKRq4pZnOB+FR6seoN2xCTMJ0doVmdV5KjQsL2/UziSloj1R+PohJZpuHarhALv9liChtgi+uPLz1NPWAc9aq1w4ikIXtVLXu4XQDtrgAdo4gy9l8BBpRqVgLd3HG0oiCPD6te27jWfMJ23FenybnqE6+kUyfDMbGDYODy+a40PjbR4+Z82Mi2J+Rf3t2IALHVX5+GBUe4OuI1FGtAXEPN28eTyYVu3YiaG9uIGQJlxvYcxdAgdn5f1N0jwXRrKibfKFdgGbxELCHBl2FGZFSYfrjF3hxNv4YpAhIfVr+5OfV6dqRJgDesCChbZvURnXKswtP2jloZC7UnDhAAnpRTVkv1uROeEUgtyqRyLev1zi7yPSBXTD84l0xHHLchffOdUGosZ5mu/XZR0j/2xyTCxtyN+V54NPpfGFMMK1+CcEjRRurwEgGNPj6jW2iLNa8k8nomGcYmHCzD+K/Pedu10VjMV/TO/gVfCT6wMktMjWfncBPPP2kmaiPKRouBv4WNUsswCz1nftQvKdv2jQR6UKZb10o8gVQoRXLIzGVgGbwV+gAhb/lPrBjmTQz5juqCPWpcd1y9ydDL+xoNF0jTKqjzpGUc3N0OQeGF50AxsxdGlCMEodMGCe/7DWD80enXFwkBf/cfJSOafGB3DvIzb+Pg+Mh1nmvJ8uX6v6yLVuFaPPuN8mX2gMiqSsNisLjxg2EwYI0eQdlu0A3qm2loyDlEHXPpqhCEMZ/aUHE0ewuR/9GUFDZnA5kOas8do7ug1+Xi6JTf6w38JCVjTqjLoKbIxDvSU3NiFQBkfZ3yuqZKDce+tl6QELZntrtDBSBIYZ2OdUFs89ptxj53/MK6o9E93XOO5v9dyOY7unTZ4eLxk4f8Hl9LBM0T/1GY7i262wjraXr16Z7O5+yIAfcmhzMI07rE9LMijiYXIfd1yLO9458vGFFQ7odCDHh2gmKZCHk1oxvr++hbGV18w+kQjizp8gJx5IG4i9fCmzX6SEDLtBmHlfwccwpQFU5h5Pt0az3FLAjMhIIc+VPinjuWZMfurzBzQ9uyq3YwY7bwce1EAWhPYhqjI932JJEdnghBBmPtlckXxftN9snTx9CQkfjThrIiAwNlq/Y08/56ErwlhUFf8sCaQ2Iw5iZVQmVehrgh1mzZBiMhT37KRaLdH7pblMEcaL2JVPZIDEsAwBhLzuvUAtj63W9Q3JTEpdn5bQdKyZEIih2yQyBKWRLiKIFGR3DQKBu/GRNjfp/gT5Nf7vISyB3bh3fPNTs+1944SIgyh0xdMmIdsRTLM+TfNDyLhyZEp5ef7YhW2uvYMYgYxTbUJimKo/AKpi9uOeIJVjlCzj3SEq+N1rSADw7wbirLc1q7gSAnv/ks5XQYSvpI08kbk0eQMqEama3v3wFGUSIWvZQXe3HPOJiij44XiOEhDW69TifCJbgD4aPBve1kLxQrp9nx6mPFnmnndNg3vQBDwzXIXFbEfLgV+DiNZ0S6pqNZpmcCGDxuvKbu0RDLP/GWuHqITW8ML2UeEGrxlU0LMbVCFR2f4Zuj9c2QmGJ1xOpWqVYbJtL+isinXuHlxQR13ibCRlgffwFd/UE7VVKLPx4usMf4SADen4XEzHEYgDxRmO8jljlaJpXTtP7ADPPP+xRCZlGSJx8BK5ETD9ATOuigv8AiXpWey6uKGvc7Z4z6Ryik1C5iF0L7JO5POsrfldVWNSDUqIHBVs2TACzVkx22C75jjHDKvcO1UIJaL4rc8DtU9GoAmHpP+qOmW4JnSMS/cFjYACCIxYuAgBfORMzpAirxqSXYDstYVLWiHlNgxkzTX8+zv51jx/0HpuOBOyvwbTS2w2RYmvP0dazy05ZIEKUAe0CNcQPsiQah1d6iHtBUht/U7/Wk9FHUJj4r61/76jGqQXilRJg58LsoaUf+4DSZrycSrxh";
		String pwd = "z6bdMvEyYC/7SewJ1N2wVSi3Jq+CPNj8xeoAXCYqaLA=";
		byte[] temp1 = decrypt(des, pwd);
		System.out.println(new String(temp1));
	}
}
